/*
 * postscript.h
 *
 *  Created on: Sep 20, 2011
 *      Author: lindenb
 */

#ifndef POSTSCRIPT_H_
#define POSTSCRIPT_H_
#include <iostream>
#include <vector>
#include <stdint.h>

#define PS_FUN(fun) Postscript& fun() { out() << #fun << std::endl;return *this;}
#define PS_FUN1(fun,type) Postscript& fun(type a) { out() << a << " " << #fun << std::endl;return *this;}
#define PS_FUN2(fun,type) Postscript& fun(type x,type y) { out() << x << " " << y << " " << #fun  << std::endl;return *this;}
#define PS_FUN3(fun,type) Postscript& fun(type a,type b, type c) { out() << a << " " << b << " "<< c << " " << #fun  << std::endl;return *this;}
#define PS_COLOR(c,r,g,b) Postscript& c() { return setrgbcolor(r,g,b);}
class Postscript
	{
	public:
		typedef float size_type;

	private:
		uint32_t pageCount;
		std::ostream& _out;
		void escape(char c);
	public:
		typedef float pixel_t;
		struct Point
			{
			pixel_t x;
			pixel_t y;
			};
		Postscript(std::ostream& out);
		~Postscript();
		std::ostream& out() { return _out;}
		PS_FUN(gsave);
		PS_FUN(setfont);
		PS_FUN(newpath);
		PS_FUN(closepath);
		PS_FUN(fill);
		PS_FUN(stroke);
		PS_FUN(grestore);
		PS_FUN(showpage);
		PS_FUN1(rotate,float);
		PS_FUN1(setlinewidth,float);
		PS_FUN1(scalefont,float);
		PS_FUN1(setgray,float);
		PS_FUN2(moveto,size_type);
		PS_FUN2(lineto,size_type);
		PS_FUN2(rmoveto,size_type);
		PS_FUN2(rlineto,size_type);
		PS_FUN2(translate,size_type);
		PS_FUN2(scale,size_type);
		PS_FUN3(setrgbcolor,float);
		Postscript& findfont(const char* font);
		Postscript& path(const Point* pt,std::size_t n);
		Postscript& path(const std::vector<Point>& pt);
		Postscript& show(const char* s);
		Postscript& setfont(const char* s,pixel_t size);
		PS_COLOR(red,1,0,0)
		PS_COLOR(green,0,1,0)
		PS_COLOR(magenta,1,0,1)
		PS_COLOR(yellow,1,1,0)
		PS_COLOR(white,1,1,1)
		PS_COLOR(black,0,0,0)
		PS_COLOR(orange,1.0,0.7,0.0)
		PS_COLOR(purple,0.7,0.3,1.0)
		PS_COLOR(brown,0.7,0.3,0.0)
		Postscript& comment(const char* s);
		Postscript& line(size_type x1,size_type y1,size_type x2,size_type y2);
		Postscript& rect(size_type x,size_type y,size_type width,size_type height);
		Postscript& rect(size_type width,size_type height);
	};


class GState
	{
	private:
		Postscript* _ps;
		GState(const GState& cp){}
	public:
		GState(Postscript* ps):_ps(ps) {_ps->gsave();}
		~GState(){_ps->grestore();}
		Postscript* ps() { return _ps;}
	};

#undef PS_COLOR
#undef PS_FUN
#undef PS_FUN2
#undef PS_FUN3
#endif /* POSTSCRIPT_H_ */
